package com.study.custom.view;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.study.custom.bean.TrendData;
import com.study.custom.util.LogUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 折线图
 */
public class ZheXianTuView extends View {
    private TextPaint numTextPaint; // 折线图左标注
    private TextPaint dateTextPaint; // 日期标注

    private Paint dividingPaint; // 折线分割线
    private Paint coordinatePaint; // 坐标
    private Paint brokenLinePaint; // 折线
    private Paint touchLinePaint; // 触摸直线
    private Paint tipTextPaint; // 提示框文字

    private Path brokenLinePath; // 折线

    private List<String> rightNumList = new ArrayList<>(); // 左边的数字
    private List<String> dateList = new ArrayList<>(); // 日期
    private List<String> numList = new ArrayList<>(); // 坐标点

    private int numPadding = dp2px(30); // 数字间隔
    private int marginTop = dp2px(30); // 距离顶部的距离
    private int marginLeft = dp2px(10); // 距离左边的距离
    private int maringRight = dp2px(10); // 距离左边的距离
    private int textMaxWidth; // 文字最大宽度

    private int dividingWidth = 0; // 分割线宽度
    private int dividingHeight = 0; // 分割线高度

    private int maxNum; // 最大的坐标点
    private int minNum; // 最小的坐标点

    private int maxSection = 6000; // 最大区间
    private int minSection = 1000; // 最小区间

    private int sectionNum = 6; // 区间个数
    private float radiusSize = 5; // 圆环半径

    // 计算后的x,y坐标
    private List<PointF> mPoints = new ArrayList<>();
    private List<PointF> mShowPoints = new ArrayList<>();

    private float touchX = -1;
    private float touchY = -1;

    private float minY = 0; // 触摸直线的顶点
    private float maxY = 0; // 触摸直线的最低点

    private List<TrendData> data = new ArrayList<>(); // 数据

    public ZheXianTuView(Context context) {
        this(context, null);
    }

    public ZheXianTuView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ZheXianTuView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        initPaint();
        initData();
        findExtremeNum();
//        findSection();
    }

    // 计算点坐标
    private void initPoints() {
        mPoints.clear();
        mShowPoints.clear();

        for (int i = 0; i < numList.size(); i++) {
            mPoints.add(new PointF(getXSpot(i), getYSpot(i)));
            mShowPoints.add(new PointF(getXSpot(i), getYSpot(i)));

//            LogUtil.i("mPoints:" + mPoints.size());
//            LogUtil.i("mShowPoints:" + mShowPoints.size());
        }
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        numTextPaint = new TextPaint();
        numTextPaint.setColor(Color.parseColor("#6A6A6A"));
        numTextPaint.setAntiAlias(true); // 抗锯齿
        numTextPaint.setTextSize(30); // 文字大小
        numTextPaint.setStyle(Paint.Style.FILL); // 文字风格

        dateTextPaint = new TextPaint();
        dateTextPaint.setColor(Color.parseColor("#6A6A6A"));
        dateTextPaint.setAntiAlias(true); // 抗锯齿
        dateTextPaint.setTextSize(40); // 文字大小
        dateTextPaint.setStyle(Paint.Style.FILL); // 文字风格

        dividingPaint = new Paint();
        dividingPaint.setColor(Color.parseColor("#6A6A6A"));
        dividingPaint.setAntiAlias(true); // 抗锯齿
        dividingPaint.setStrokeWidth(2);
        dividingPaint.setStyle(Paint.Style.FILL);

        coordinatePaint = new Paint();
        coordinatePaint.setColor(Color.parseColor("#159040")); // 绿色
        coordinatePaint.setAntiAlias(true); // 抗锯齿
        coordinatePaint.setStrokeWidth(5);
        coordinatePaint.setStyle(Paint.Style.STROKE);

        brokenLinePaint = new Paint();
        brokenLinePaint.setColor(Color.parseColor("#159040"));
        brokenLinePaint.setAntiAlias(true); // 抗锯齿
        brokenLinePaint.setStrokeWidth(5);
        brokenLinePaint.setStyle(Paint.Style.STROKE);

        brokenLinePath = new Path();


        touchLinePaint = new Paint();
        touchLinePaint.setColor(Color.parseColor("#6A6A6A"));
        touchLinePaint.setAntiAlias(true); // 抗锯齿
        touchLinePaint.setStrokeWidth(5);
        touchLinePaint.setStyle(Paint.Style.STROKE);

        tipTextPaint = new Paint();
        tipTextPaint.setColor(Color.parseColor("#ffffff"));
        tipTextPaint.setAntiAlias(true); // 抗锯齿
        tipTextPaint.setTextSize(30); // 文字大小
        tipTextPaint.setStyle(Paint.Style.FILL); // 文字风格
    }

    /**
     * 测用数据
     */
    private void initData() {
        setRightNum();


        dateList.add("01-01");
        dateList.add("01-02");
        dateList.add("01-03");
        dateList.add("01-04");
        dateList.add("01-05");
        dateList.add("01-06");
        dateList.add("01-07");


        numList.add("2200");
        numList.add("2300");
        numList.add("2200");
        numList.add("2200");
        numList.add("2200");
        numList.add("1900");
        numList.add("3600");

        for (int i = 0; i < 7; i++) {
            TrendData currentData = new TrendData();
            currentData.setDate("日期：" + i);
            currentData.setTodayMoney("今日：" + i + "000");
            currentData.setYearsTodayMoney("昨日：" + i + "000");
            currentData.setNewAdd("新增：" + i);
            data.add(currentData);
        }
    }

    /**
     * 设置左边的坐标数据
     */
    private void setRightNum() {
        int currentNum = maxSection - minSection;
        int intervalValue = currentNum / (sectionNum - 1); // 间隔值

        for (int i = 0; i < sectionNum; i++) {
            rightNumList.add("" + (maxSection - intervalValue * i));
        }
    }

    /**
     * 找到数据极值
     * 最大值
     * 最小值
     */
    private void findExtremeNum() {
        minNum = 0;
        maxNum = 0;
        if (null == numList || numList.size() == 0) {
            minNum = 0;
            maxNum = 0;
        }

        try {
            for (int i = 0; i < numList.size(); i++) {
                if (Integer.valueOf(numList.get(i)) > maxNum) {
                    maxNum = Integer.valueOf(numList.get(i));
                }

                minNum = Integer.valueOf(numList.get(0));
                if (Integer.valueOf(numList.get(i)) < minNum) {
                    minNum = Integer.valueOf(numList.get(i));
                }
            }
        } catch (Exception e) {
            minNum = 0;
            maxNum = 0;
            LogUtil.e("数字格式错误！数字类型转换失败");
        }

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 计算坐标点
        initPoints();
        drawLeftText(canvas); // 画左边的数字和分割线
        drawDate(canvas); // 画日期
        drawCoordinate(canvas); // 画坐标点
        drawBrokenLine(canvas); // 画光滑的折线
//        drawBrokenLineDefault(canvas); // 或没有弧度的折线
        drawTouchLine(canvas); // 画触摸点的直线

        List<String> currentData = new ArrayList<>();
        currentData.add(data.get(0).getDate());
        currentData.add(data.get(0).getTodayMoney());
        currentData.add(data.get(0).getYearsTodayMoney());
        currentData.add(data.get(0).getNewAdd());

        drawTextView(canvas, currentData);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) { // 点击事件 TODO MWB
        touchX = event.getX();
        touchY = event.getY();
        postInvalidate(); // 重新绘制

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchX = event.getX();
                touchY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                touchX = event.getX();
                touchY = event.getY();
                break;
        }

        return true;
//        return super.onTouchEvent(event);
    }

    /**
     * 画左边的数字
     */
    private void drawLeftText(Canvas canvas) {
        if (null == rightNumList || rightNumList.size() == 0) {
            return;
        }

        int currentHeight = 0; // 去除margin的高度

        for (int i = 0; i < rightNumList.size(); i++) {
            // 写左边的字
            canvas.drawText(rightNumList.get(i), marginLeft, getTextHeight(numTextPaint, rightNumList.get(i)) + i * marginTop,
                    numTextPaint);

            // 画分割线
            canvas.drawLine(marginLeft * 2 + getTextWidth(numTextPaint, rightNumList.get(i)),
                    getTextHeight(numTextPaint, rightNumList.get(i)) - (getTextHeight(numTextPaint, rightNumList.get(i)) / 2) + i * marginTop,
                    getWidth() - maringRight,
                    getTextHeight(numTextPaint, rightNumList.get(i)) - (getTextHeight(numTextPaint, rightNumList.get(i)) / 2) + i * marginTop,
                    dividingPaint);

            if (getTextWidth(numTextPaint, rightNumList.get(i)) > textMaxWidth) {
                textMaxWidth = getTextWidth(numTextPaint, rightNumList.get(i));
            }

            if (i == 0) { // 获取极值
                minY = getTextHeight(numTextPaint, rightNumList.get(i)) - (getTextHeight(numTextPaint, rightNumList.get(i)) / 2) + i * marginTop;
            }

            if (i == rightNumList.size() - 1) { // 获取极值
                maxY = getTextHeight(numTextPaint, rightNumList.get(i)) - (getTextHeight(numTextPaint, rightNumList.get(i)) / 2) + i * marginTop;
            }
        }

        dividingHeight = marginTop * (sectionNum - 1) + getTextHeight(numTextPaint, "0") / 2;
        dividingWidth = getWidth() - marginLeft - marginLeft - maringRight - textMaxWidth;

    }

    /**
     * 画日期
     *
     * @param canvas
     */
    private void drawDate(Canvas canvas) {
        int viewHeight = getTextHeight(numTextPaint, "0") + rightNumList.size() * marginTop;

        int jianGe = dividingWidth / (dateList.size() - 1); // 分割线间距

        for (int i = 0; i < dateList.size(); i++) {
            canvas.drawText(dateList.get(i),
                    (maringRight + maringRight + textMaxWidth - getTextWidth(dateTextPaint, dateList.get(i)) / 2) + jianGe * i,
                    viewHeight, numTextPaint);
        }
    }

    /**
     * 画坐标点
     */
    private void drawCoordinate(Canvas canvas) {

        List<String> currentNum = new ArrayList<>();
        for (int i = 0; i < numList.size(); i++) {
            currentNum.add("" + (Integer.parseInt(numList.get(i)) - minSection));
        }

        float fDividingHeight = dividingHeight;
        float coordinateHeight = dividingHeight - (getTextHeight(numTextPaint, "0") / 2); // 当前坐标最大高度(去除文字一半高度)


        int jianGe = dividingWidth / (currentNum.size() - 1); // 分割线间距

        for (int i = 0; i < currentNum.size(); i++) {
            float currentY;
            currentY = fDividingHeight - (Float.parseFloat(currentNum.get(i)) / (maxSection - minSection) * coordinateHeight);

            canvas.drawCircle((maringRight + maringRight + textMaxWidth) + jianGe * i,
                    currentY,
                    radiusSize,
                    coordinatePaint);
        }
    }

    /**
     * 画折线
     */
    private void drawBrokenLine(Canvas canvas) {
        brokenLinePath.reset(); // 重置绘制路径

        if (null == numList || numList.size() == 0) {
            return;
        }
        brokenLinePath.moveTo(getXSpot(0),
                getYSpot(0)); // 移动到第一个点的坐标

        for (int i = 0; i < numList.size() - 1; i++) {
            brokenLinePath.cubicTo(
                    getXSpot(i) + (getXSpot(i + 1) - getXSpot(i)) / 2,
                    getYPointOne(i),
                    getXSpot(i) + (getXSpot(i + 1) - getXSpot(i)) / 2,
                    getYPointTwo(i),
                    getXSpot(i + 1),
                    getYSpot(i + 1)
            );
        }

        canvas.drawPath(brokenLinePath, brokenLinePaint);

    }

    /**
     * 默认是折线，不光滑
     *
     * @param canvas
     */
    private void drawBrokenLineDefault(Canvas canvas) {
        for (int i = 0; i < numList.size(); i++) { // 画折线 解开此刻方法
            if (i == numList.size() - 1) {
                return;
            }
            canvas.drawLine(getXSpot(i),
                    getYSpot(i),
                    getXSpot(i + 1),
                    getYSpot(i + 1),
                    brokenLinePaint);
        }

        canvas.drawPath(brokenLinePath, brokenLinePaint);
    }

    /**
     * 画触摸点的直线 TODO MWB
     */
    private void drawTouchLine(Canvas canvas) {
        if (touchY == -1 || touchX == -1) { // 没有触摸不用绘制
            return;
        }

//        mPoints TODO MWB
        float currentX = 0;
        // 每段分割线的宽度 = 分割线宽度 / numList.size() -1
        float divisionWidth = dividingWidth / (numList.size() - 1);

        for (int i = 0; i < mPoints.size(); i++) {
            if (i == 0) {
                if (touchX < mPoints.get(i).x + divisionWidth / 2) {
                    currentX = mPoints.get(i).x;
                }
            } else {
                if (touchX > mPoints.get(i - 1).x + divisionWidth / 2 && touchX < mPoints.get(i).x + divisionWidth / 2) {
                    currentX = mPoints.get(i).x;
                }
            }
        }

        canvas.drawLine(currentX,
                minY,
                currentX,
                maxY,
                touchLinePaint);

    }


    /**
     * 画随手而动的直线
     */
    private void drawTouchLineFlowFinger(Canvas canvas) {
        if (touchY == -1 || touchX == -1) { // 没有触摸不用绘制
            return;
        }
        canvas.drawLine(touchX, // 随手而动的线
                minY,
                touchX,
                maxY,
                touchLinePaint);
    }

    /**
     * 画提示框和文字
     *
     * @param canvas
     * @param currentData
     */
    private void drawTextView(Canvas canvas, List<String> currentData) {
        if (touchX == 0 || touchY == 0) {
            return;
        }

        if (null == currentData || currentData.size() == 0) {
            return;
        }

        float textPaddingTop = getTextHeight(tipTextPaint, "0"); // 提示文字上间距
        float textPaddingLeftRift = getTextWidth(tipTextPaint, "0") / 2; // 提示文字左右间距
        float currentTextHeight = getTextHeight(tipTextPaint, "0"); // 文字高度

        float tipMaxY = 0; // 提示框最大宽度
        float tipMaxX = 0; // 提示框最大高度

        tipMaxX = getTipMaxX(currentData);
        tipMaxY = getTipMaxY(currentData); //


        RectF rectF = new RectF(touchX - tipMaxX - (textPaddingLeftRift * 3),
                touchY - tipMaxY,
                touchX, touchY);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//创建画笔
        paint.setColor(Color.parseColor("#99000000"));
        canvas.drawRoundRect(rectF, 10, 10, paint);

        for (int i = 0; i < currentData.size(); i++) { // 写字
            canvas.drawText(currentData.get(i),
                    touchX - tipMaxX - textPaddingLeftRift,
                    touchY - tipMaxY + textPaddingTop + (currentTextHeight * (i + 1)) + (i * currentTextHeight),
                    tipTextPaint);
        }

    }

    /**
     * 获取提示框最大宽度
     */
    private float getTipMaxX(List<String> currentData) {
        float maxX = 0;

        for (int i = 0; i < currentData.size(); i++) {
            if (maxX < getTextWidth(tipTextPaint, currentData.get(i))) {
                maxX = getTextWidth(tipTextPaint, currentData.get(i));
            }
        }

        return maxX;
    }

    /**
     * 获取提示框最大高度
     *
     * @return
     */
    public float getTipMaxY(List<String> currentData) {
        float tipMaxY = 0;

        for (int i = 0; i < currentData.size(); i++) {
            tipMaxY += getTextHeight(tipTextPaint, currentData.get(i)) + (getTextHeight(tipTextPaint, currentData.get(i)) / 2);
        }

        tipMaxY += (getTextHeight(tipTextPaint, currentData.get(0))) * 3; // 多一个
        return tipMaxY;
    }


    /**
     * 获取坐标的X点坐标
     *
     * @param indx 第几个点
     * @return
     */
    private float getXSpot(int indx) {
        if (null == numList || numList.size() == 0) {
            return 0;
        }

        float maxMarginLeft = textMaxWidth + marginLeft + marginLeft; // 坐标距离屏幕左边最大距离
        float widthInterval = dividingWidth / (numList.size() - 1); // 间隔距离

        if (indx == 0) {
            return getTextWidth(numTextPaint, numList.get(0)) + marginLeft + marginLeft;
        } else {
            return maxMarginLeft + widthInterval * indx;
        }
    }

    /**
     * 获取坐标的Y点坐标
     *
     * @param indx 第几个点
     * @return
     */
    private float getYSpot(int indx) {
        List<String> currentNum = new ArrayList<>();
        for (int i = 0; i < numList.size(); i++) {
            currentNum.add("" + (Integer.parseInt(numList.get(i)) - minSection));
        }

        float fDividingHeight = dividingHeight;
        float coordinateHeight = dividingHeight - (getTextHeight(numTextPaint, "0") / 2); // 当前坐标最大高度(去除文字一半高度)

        float currentY;
        currentY = fDividingHeight - (Float.parseFloat(currentNum.get(indx)) / (maxSection - minSection) * coordinateHeight);
        return currentY;
    }


    /**
     * dp转px
     *
     * @param dp
     * @return
     */
    private int dp2px(int dp) {
        return (int) (Resources.getSystem().getDisplayMetrics().density * dp + 0.5);
    }

    /**
     * 获取文字的高度
     *
     * @param paint
     * @param text
     * @return
     */
    private int getTextHeight(Paint paint, String text) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect.height();
    }

    /**
     * 获取文字的宽度
     *
     * @param paint
     * @param text
     * @return
     */
    private int getTextWidth(Paint paint, String text) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect.width();
    }

    /**
     * 三阶贝塞尔第一个Y控制点
     *
     * @return
     */
    public float getYPointOne(int index) {

        float firstP = getYSpot(index);
        float endP = getYSpot(index + 1);
        // 判断是升还是降
        if (firstP > endP) { // 是升的（注意此处关系，对应Y轴坐标系）
            return getYSpot(index) - (getYSpot(index) - getYSpot(index + 1)) / 4;
        } else { // 是降的
            return getYSpot(index) + (getYSpot(index + 1) - getYSpot(index)) / 4;
        }
    }

    /**
     * 三阶贝塞尔第二个Y控制点
     *
     * @return
     */
    public float getYPointTwo(int index) {
        float firstP = getYSpot(index);
        float endP = getYSpot(index + 1);
        // 判断是升还是降
        if (firstP > endP) { // 是升的（注意此处关系，对应Y轴坐标系）
            return getYSpot(index + 1) + (getYSpot(index) - getYSpot(index + 1)) / 4;
        } else { // 是降的
            return getYSpot(index + 1) - (getYSpot(index + 1) - getYSpot(index)) / 4;
        }
    }

}
